package demos.consumer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeUnit;

public class MyBlockingQueue3<T> {
    public static void main(String[] args) {
        MyBlockingQueue3<Integer> queue3 = new MyBlockingQueue3<>(3);
        new Thread(() -> {
            for (int i = 0; i < 10; ++i) {
                queue3.put(i);
            }
        }).start();
        new Thread(() -> {
            for (int i = 0; i < 10; ++i) {
                queue3.take();
            }
        }).start();
    }

    private final int capacity;
    private int size = 0;
    private Queue<T> queue = new LinkedList<>();

    public MyBlockingQueue3(int capacity) {
        this.capacity = capacity;
    }

    public void put(T data) {
        synchronized (this) {
            try {
                while (size == capacity) {
                    this.wait();
                }
                queue.add(data);
                size++;
                System.out.println("put in, size = " + size);
                this.notifyAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public T take() {
        T t = null;
        synchronized (this) {
            try {
                while (size == 0) {
                    this.wait();
                }
                t = queue.remove();
                size--;
                System.out.println("    take out, size = " + size);
                this.notifyAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return t;
    }
}
